public class UT_SObjectFactory {

    public static Id DefBHId = [select Id From BusinessHours Where IsDefault=True].Id;

    //
    // This is the newer factory version.  It makes a chain of interconnected objects.
    // 
    public class InterconnectedSObjectsForNCSP {
        public Contact c;
        public Account a;
        public Support_Program__c sp;
        public Entitlement__c e;
        public Program_Contact__c pc;
        public List<Asset> assArr;
        public List<Program_Asset__c> paArr;
        public InterconnectedSObjectsForNCSP(Boolean bApplyToAll, Integer numAssets) {
            this.a = new Account(Name='test account',Support_Program__c=null);
            insert this.a;          
            this.c = new Contact(LastName='test contact',AccountId=this.a.Id);
            insert this.c;
            this.sp = new Support_Program__c( Apply_To_All_Contacts_In_Account__c = bApplyToAll, 
                Account__c = this.a.Id, RecordTypeId=RT.NCSPId );
            insert this.sp;
            this.e = new Entitlement__c(Name='TestEnt',IsDefault__c=False,Support_Program__c=this.sp.Id,Business_Hours__c=DefBHId);
            insert this.e;
            this.pc = new Program_Contact__c( Contact__c = this.c.Id, Support_Program__c=this.sp.Id );
            insert this.pc;
            
            this.paArr = new List<Program_Asset__c>();
            this.assArr = new List<Asset>();
            for(Integer i = 0; i<numAssets; ++i) {
                Asset ass = new Asset(Name='UT-ASSET-'+i,AccountId=this.a.Id,ContactId=this.c.Id);
                assArr.add(ass);
            } 
            insert assArr;           
            for(Integer i = 0; i<numAssets; ++i) {
                Program_Asset__c pa = new Program_Asset__c( Asset__c=assArr[i].Id, Support_Program__c=this.sp.Id );
                paArr.add(pa);
            }
            insert paArr;
        }
        public Entitlement__c addDefEnt() {
            Entitlement__c de = new Entitlement__c(Name='TestEnt-Def',IsDefault__c=True,Support_Program__c=this.sp.Id,Business_Hours__c=DefBHId);
            insert de;
            this.sp.DefEntHint__c = de.Id;
            update this.sp;
            return de;
        }
    }
 
 	// Creates a separate MASP and NCSP which share a single Contact/Account
    public class InterconnectedSObjectsForSharedSPPairWithDEs {
    	public Account a;
    	public Contact c;
    	public Support_Program__c masp;
    	public Support_Program__c ncsp;
    	public Entitlement__c maspDefEnt;
    	public Entitlement__c ncspDefEnt;
    	public InterconnectedSObjectsForSharedSPPairWithDEs() {
    		InterconnectedSObjectsForNCSP n = new InterconnectedSObjectsForNCSP(false,0);
    		this.ncspDefEnt = n.addDefEnt();
    		InterconnectedSObjectsForMASP m = new InterconnectedSObjectsForMASP(1);
    		this.maspDefEnt = m.addDefEnt();
    		this.a = new Account(Id=n.a.Id,Support_Program__c=m.sp.Id); update this.a;
    		this.c = n.c;
    		this.ncsp = n.sp;
    		this.masp = m.sp;
    	}
    }
    
    public class InterconnectedSObjectsForContact {
        public Contact c;
        public Account a;
        public Support_Program__c sp;
        public Entitlement__c e;
        public Program_Contact__c pc;
        public InterconnectedSObjectsForContact() {
            InterconnectedSObjectsForNCSP o = new InterconnectedSObjectsForNCSP(true,0);
            this.c = o.c;
            this.a = o.a;
            this.sp = o.sp;
            this.e = o.e;
            this.pc = o.pc;
        }
    }
    
    public class InterconnectedSObjectsForMASP {
        public Contact c;
        public Account a;
        public Support_Program__c sp;
        public List<Entitlement__c> eArr;
        public InterconnectedSObjectsForMASP(Integer numEntitlements) {
            this.a = new Account(Name='test account',Support_Program__c=null);
            insert this.a;          
            this.c = new Contact(LastName='test contact',AccountId=this.a.Id);
            insert this.c;
            this.sp = new Support_Program__c( Apply_To_All_Contacts_In_Account__c = true, 
                Account__c = null, RecordTypeId=RT.MASPId, Name='TEST-MASP' );
            insert this.sp;
            this.a.Support_Program__c = this.sp.Id;
            update this.a;
            
            this.eArr = new List<Entitlement__c>();
            for (Integer i=0; i<numEntitlements; i++) {
                Entitlement__c e = new Entitlement__c(Name='TEST_E-'+i,
                    Support_Program__c=this.sp.Id, IsDefault__c=False,
                    Business_Hours__c=DefBHId);
                this.eArr.add(e);
            }
            insert this.eArr;
        }
        public Entitlement__c addDefEnt() {
            Entitlement__c de = new Entitlement__c(Name='TestEnt-Def',IsDefault__c=True,Support_Program__c=this.sp.Id,Business_Hours__c=DefBHId);
            insert de;
            this.sp.DefEntHint__c = de.Id;
            update this.sp;
            return de;
        }
    }
    
    static testMethod void testMakeInterconnectedContact() { 
        InterconnectedSObjectsForContact o = new InterconnectedSObjectsForContact();
        system.assert( o.a != null); 
        system.assert( o.sp != null);
        system.assert( o.c != null);
        system.assert( o.pc != null);
        system.assert( o.e != null);
    }
    
    public class InterconnectedSObjectsAssetContract {
        public Contact c;
        public Account a;
        public Support_Program__c sp;
        public Entitlement__c e;
        public Program_Contact__c pc;
        public Asset ass;
        public Contract contr;
        public InterconnectedSObjectsAssetContract() {
//            InterconnectedSObjectsForContact o = new InterconnectedSObjectsForContact();
            InterconnectedSObjectsForNCSP o = new InterconnectedSObjectsForNCSP(true,1);
            this.a = o.a;           
            this.c = o.c;
            this.sp = o.sp;
            this.e = o.e;
            this.pc = o.pc;
            this.contr = new Contract(AccountId=this.a.Id); 
            insert this.contr;
//            this.ass = new Asset(Name='UT-ASSET',AccountId=this.a.Id,ContactId=this.c.Id); 
//            insert this.ass;
            this.ass = o.assArr[0];
        }
    }
    
    static testMethod void testMakeInterconnectedAssetContract() { 
        InterconnectedSObjectsAssetContract o = new InterconnectedSObjectsAssetContract();
        system.assert( o.ass != null); 
        system.assert( o.contr != null);
        system.assert( o.a != null);
        system.assert( o.pc != null);
        system.assert( o.c != null);
        system.assert( o.sp != null);
        system.assert( o.e != null);        
    }

}